﻿using Kele.Activity.Core;
using Kele.Activity.Helper;
using Kele.Activity.Models;
using Kele.Activity.Models.Dto;
using Kele.Repository;
using Newtonsoft.Json;
using Senparc.CO2NET.Extensions;
using SqlKata;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Kele.Activity.Service
{
    public partial class ActivityService
    {
        public async Task<ActivityEntity> GetActivityAsync(int id)
        {

            var tableName = AppReflection.GetTableName<ActivityEntity>();
            var cacheKey = AppCache.GetEntityKey(tableName, id);
            return await AppRepository.FirstOrDefaultAsync<ActivityEntity>(id, tableName, cacheKey);
        }

        public async Task<dynamic> GetActivityDetailAsync(int merchantId, int id)
        {
            var activity = await GetActivityAsync(id);

            var formList = await AppService.Form.GetFormListAsync();
            var form = formList.FirstOrDefault(f => f.Id == activity.FormId);

            var skinList = await GetSkinListAsync();
            var skin = skinList.FirstOrDefault(s => s.Id == activity.SkinId);

            return new
            {
                activity_id = activity.Id,
                activity.Title,
                activity.CreatedDate,
                activity.StartTime,
                activity.EndTime,
                activity.BrowseNum,
                activity.BuyerNum,
                activity.ShareNum,
                activity.SoldNum,
                activity.Status,
                top_images = activity.TopImages?.ToJArray(),
                images = activity.Images,
                stores = activity.Stores?.ToJArray(),
                props = activity.Props?.ToJObject(),
                activity.MusicId,
                activity.Rule,
                activity.Description,
                fields = activity.Fields?.ToJArray(),
                activity.IsRecommend,
                skin_id = skin?.Id,
                skin_alias = skin?.Alias,
                skin?.SkinName,
                activity.FormId,
                form?.Alias,
                url = $"https://{activity.Id}.wx.adtaoke.cn"
            };
        }

        public async Task<dynamic> GetActivityListAsync(int merchantId, ActivityListInputDto dto)
        {
            var query = new Query();
            query.Where("merchant_id", merchantId)
                 .When(dto.form_id > 0, q => q.Where("form_id", dto.form_id))
                 .When(!string.IsNullOrEmpty(dto.title), q => q.WhereLike("title", dto.title));

            var now = DateTime.Now;
            switch (dto.processStatus)
            {
                case 1:
                    query.Where("start_time", ">", now);
                    break;

                case 2:
                    query.Where("start_time", "<=", now).Where("end_time", ">", now);
                    break;

                case 3:
                    query.Where("end_time", "<=", now);
                    break;
            }

            var paginateResult = await AppRepository.PaginateAsync<ActivityEntity>(dto.skip, dto.take, query);
            var skinList = (await GetSkinListAsync()).ToArray();
            var formList = (await AppService.Form.GetFormListAsync()).ToArray();
            var data = paginateResult.List.Select(x =>
            {
                var form = formList.FirstOrDefault(f => f.Id == x.FormId);
                var skin = skinList.FirstOrDefault(s => s.Id == x.SkinId);
                return new
                {
                    activity_id = x.Id,
                    x.Title,
                    x.CreatedDate,
                    x.StartTime,
                    x.EndTime,
                    x.BrowseNum,
                    x.BuyerNum,
                    x.ShareNum,
                    x.SoldNum,
                    x.Status,
                    top_images = x.TopImages?.ToJArray(),
                    images = x.Images,
                    stores = x.Stores?.ToJArray(),
                    props = x.Props?.ToJObject(),
                    x.MusicId,
                    x.Rule,
                    x.Description,
                    fields = x.Fields?.ToJArray(),
                    x.IsRecommend,
                    skin_id = skin?.Id,
                    skin_alias = skin?.Alias,
                    skin?.SkinName,
                    x.FormId,
                    form?.Alias,
                    url = $"https://{x.Id}.wx.adtaoke.cn"
                };
            }).ToList();
            return new { total = paginateResult.Count, data };
        }


        public async Task<dynamic> CreateActivityAsync(int merchantId, ActivityInputDto dto)
        {
            var error = await ValidActivityInputDto(dto);
            if (string.IsNullOrEmpty(error)) return new { error };
            var values = new Dictionary<string, object>
            {

                { "formId", dto.FormId },
                { "merchantId",merchantId},
                { "title", dto.Title },
                { "startTime", dto.StartTime },
                { "endTime", dto.EndTime },
                { "rule", dto.Rule } ,
                { "description", dto.Description },
                { "status", (int)ActivityStatus.Offline },
                { "musicId", dto.MusicId } ,
                { "skinId", dto.SkinId } ,
                { "IsRecommend", dto.IsRecommend } ,
                { "topImages", dto.TopImages.ToJson(true) },
                { "images", dto.Images.ToJson(true) },
                { "stores", dto.Stores.ToJson(true) },
                { "fields", dto.Fields.ToJson(true) },
                { "props", dto.Fields.ToJson(true) } ,
                { "CreatedDate", DateTime.Now } ,
                { "BuyerNum", 0 } ,
                { "BrowseNum", 0 } ,
                { "SoldNum",0 } ,
                { "ShareNum", 0 }

            };

            var id = await AppRepository.InsertGetIdAsync<ActivityEntity, int>(values);
            return id;
        }

        public async Task<dynamic> UpdateActivityAsync(int merchantId, ActivityInputDto dto)
        {

            var entity = await GetActivityAsync(dto.Id);
            if (entity.MerchantId != merchantId) throw new Exception("非法操作，你操作的不是你的活动");

            var error = await ValidActivityInputDto(dto);
            if (error != null) return new { error };
            var data = new Dictionary<string, object>
            {

                { "title", dto.Title },
                { "startTime", dto.StartTime },
                { "endTime", dto.EndTime },
                { "rule", dto.Rule } ,
                { "description", dto.Description },
                { "status", (int)ActivityStatus.Offline },
                { "musicId", dto.MusicId } ,
                { "skinId", dto.SkinId } ,
                { "IsRecommend", dto.IsRecommend } ,
                { "topImages", dto.TopImages.ToJson() },
                { "images", dto.Images.ToJson() },
                { "stores", dto.Stores.ToJson() },
                { "fields", dto.Fields.ToJson() },
                { "props", dto.Props.ToJson() } ,
                { "lastModifiedDate", DateTime.Now } ,

            };
            var talbeName = AppReflection.GetTableName<ActivityEntity>();
            var cacheKeysToRemove = new[]{
                AppCache.GetEntityKey(talbeName, dto.Id),
                AppCache.GetEntityKey(talbeName,"h5", dto.Id.ToString())
               };

            var query = new Query().Where("Id", dto.Id).Where("merchantId", merchantId);
            var affected = await AppRepository.UpdateAsync<ActivityEntity>(query, data, talbeName, cacheKeysToRemove);
            return affected;

        }
        private async Task<dynamic> UpdateActivityAsync(int merchantId, int id, object data)
        {

            var query = new Query().Where("Id", id).Where("merchantId", merchantId);
            var ret = await AppRepository.UpdateAsync<ActivityEntity>(query, data);
            return ret;
        }

        public async Task<dynamic> UpdateActivityStatusAsync(int merchantId, int id, int status)
        {

            return await UpdateActivityAsync(merchantId, id, new { status });

        }


        private async Task<dynamic> ValidActivityInputDto(ActivityInputDto dto)
        {

            var form = await AppService.Form.GetFormAsync(dto.FormId);
            var validator = new ActivityValidator();
            foreach (var group in form.Groups)
            {
                foreach (var field in group.ItemList)
                {
                    if (string.IsNullOrWhiteSpace(field.Rules)) continue;
                    var rules = JsonConvert.DeserializeObject<List<ValidationRule>>(field.Rules);
                    foreach (var rule in rules)
                    {
                        if (!validator.IsValid(field.Key, dto, rule))
                            return new
                            {
                                key = field.Key,
                                error = validator.message
                            };
                    }
                }
            }

            return null;
        }

        public async Task<dynamic> DeleteActivityAsync(int merchantId, int id)
        {
            var query = new Query().Where("Id", id).Where("merchantId", merchantId);

            var talbeName = AppReflection.GetTableName<ActivityEntity>();
            var cacheKeysToRemove = new[]{
                AppCache.GetEntityKey(talbeName, id),
                AppCache.GetEntityKey(talbeName,"h5", id.ToString())
               };
            var ret = await AppRepository.DeleteAsync<ActivityEntity>(query, talbeName, cacheKeysToRemove);
            return ret;
        }

        public async Task<dynamic> DuplicateActivityAsync(int merchantId, int id)
        {
            var query = new Query().Where("Id", id).Where("merchantId", merchantId);
            var entity = await AppRepository.FirstOrDefaultAsync<ActivityEntity>(query);
            var now = DateTime.Now;
            var values = new Dictionary<string, object>
            {

                { "formId", entity.FormId },
                { "merchantId",entity.MerchantId},
                { "title", entity.Title },
                { "startTime", now},
                { "endTime", now.AddDays(10).Date.AddSeconds(-1) },
                { "rule", entity.Rule } ,
                { "description", entity.Description },
                { "status", (int)ActivityStatus.Offline },
                { "musicId", entity.MusicId } ,
                { "skinId", entity.SkinId } ,
                { "IsRecommend", entity.IsRecommend } ,
                { "topImages", entity.TopImages },
                { "images", entity.Images },
                { "stores", entity.Stores },
                { "fields", entity.Fields },
                { "props", entity.Fields } ,
                { "CreatedDate", now } ,
                { "BuyerNum", 0 } ,
                { "BrowseNum", 0 } ,
                { "SoldNum",0 } ,
                { "ShareNum", 0 }

            };

            var ret = await AppRepository.InsertGetIdAsync<ActivityEntity, int>(values);
            return ret;

        }
    }
}